using System;
using System.Collections.Generic;
using CenterSpace.Free;
using TAC;
/// <summary>
/// Summary description for Class1
/// </summary>
namespace Arena
{
	public class Mapa
	{
		private MersenneTwister geradorAleatorio;
		private List<List<int>> mapa;
		private List<List<bool>> ocupado;
		private int X;
		private int Y;
		
		public Mapa()
		{
			geradorAleatorio = new MersenneTwister();
			criar();
		}

		public void imprimir()
		{
			int i, j;
			
			for (i = 0; i < Y; ++i)
				Console.Write("-");
			Console.WriteLine("+");
			
			for (i = 0; i < X; ++i)
			{
                for (j = 0; j < Y; ++j)
                    Console.Write(((mapa[i][j] != 0) ? ((mapa[i][j] == 2) ? "#" : "O") : ((ocupado[i][j]) ? "@" : " ")));
				Console.WriteLine("|");
			}
			
			for (i = 0; i < Y; ++i)
				Console.Write("-");
			Console.WriteLine("+");
		}

        public String pegarMapa()
        {
            int i, j;
            String retorno = "";

            for (i = 0; i < X; ++i)
            {
                for (j = 0; j < Y; ++j)
                    retorno += (((mapa[i][j] != 0) ? ((mapa[i][j] == 2) ? "#" : "O") : ((ocupado[i][j]) ? "@" : "_")));
                retorno += "\n";
            }

            return retorno;
        }

       	private void criar()
		{
			int i, j, porcentagem;

            X = 10;// geradorAleatorio.Next(7, 20);
            Y = 10;// geradorAleatorio.Next(7, 20);

			mapa = new List<List<int>>();
			for (i = 0; i < X; i++)
			{
				mapa.Add(new List<int>());
				for (j = 0; j < Y; j++)
				{
					mapa[i].Add(0);
				}
			}

			ocupado = new List<List<bool>>();
			for (i = 0; i < X; i++)
			{
				ocupado.Add(new List<bool>());
				for (j = 0; j < Y; j++)
				{
					ocupado[i].Add(false);
				}
			}

			for (i = 0; i < getX(); ++i)
			{
				for (j = 0; j < getY(); ++j)
				{
					if (validacaoBasica(i, j))
					{
						mapa[i][j] = 0;
					}
					else if (espacosSolitarios(i, j))
					{
						mapa[i][j] = 2;
					}
					else
					{
						porcentagem = geradorAleatorio.Next(100);
						if (primo(porcentagem))
						{
							mapa[i][j] = 2;
						}
						else if (!(porcentagem % 2 == 0))
						{
							mapa[i][j] = 1;
						}
						else
						{
							mapa[i][j] = 0;
						}
					}
				}
			}

			colunasSolitarias(mapa);
		}

		private bool validacaoBasica(int x, int y)
		{
			return (x > 0 && mapa[x - 1][y] == 0 && (((y < getY() - 1) ? mapa[x - 1][y + 1] != 0 : true) || ((y > 0) ? mapa[x - 1][y - 1] != 0 : true)));
		}

		private bool espacosSolitarios(int x, int y)
		{
			return (x == getX() - 1 && mapa[x - 1][y] != 0 && ((y < getY() - 1) ? mapa[x - 1][y + 1] != 0 : true) && ((y > 0) ? (mapa[x - 1][y - 1] != 0 && mapa[x][getY() - 2] != 0) : true));
		}

		private void colunasSolitarias(List<List<int>> mapa)
		{
			int auxiliar = 0;

			//excecao #2: linhas solitarias
			/*	O # O
				O # O , por exemplo.
			*/
			for (int i = 0; i < Y; i++)
			{
				auxiliar = Y;
				for (int j = 0; j < X; j++)
				{
					if (mapa[j][i] != 0)
						auxiliar--;
				}
				if (auxiliar == 0)
				{
					for (int j = 0; j < Y; j++)
					{
						if (((i > 0) ? mapa[j][i - 1] == 0 : true) && ((i < Y - 1) ? mapa[j][i + 1] == 0 : true))
						{
							mapa[j][i] = 0;
							break;
						}
					}
				}
			}
		}

		private bool primo(int n)
		{
			if (n < 2)
				return false;
			else
			{
				for (int i = 2; i <= n / 2; i++)
				{
					if (n % i == 0)
						return false;
				}
				return true;
			}
		}

		public int getX()
		{
			return X;
		}

		public int getY()
		{
			return Y;
		}

        public bool estaOcupado(int x, int y)
		{
			return ocupado[x][y];
		}


		public bool quadradoValido(int x, int y)
		{
			return ((mapa[x][y] == 0 && !ocupado[x][y]) ? true : false);
		}

		public void setOcupado(bool valor, int x, int y)
		{
			ocupado[x][y] = valor;
		}

		public List<int[]> posicoesOcupadas()
		{
			List<int[]> retorno = new List<int[]>();

			for (int i = 0; i < getX(); i++)
				for (int j = 0; j < getY(); j++)
					if (ocupado[i][j] == true)
						retorno.Add(new int[] { i, j });

			return retorno;
		}

		public List<int[]> posicoesValidas()
		{
			List<int[]> retorno = new List<int[]>();

			for (int i = 0; i < getX(); i++)
				for (int j = 0; j < getY(); j++)
					if (mapa[i][j] == 0 && !ocupado[i][j])
						retorno.Add(new int[] { i, j });

			return retorno;
		}

        public bool posicaoValida(int i, int j)
        {
            return (i < 10 && i >= 0 && j < 10 && j >=0 && mapa[i][j] == 0 && !ocupado[i][j]);
        }

        public bool posicaoCorreta(int i, int j)
        {
            return (i < 10 && i >= 0 && j < 10 && j >= 0 && mapa[i][j] == 0);
        }
	}
}